package com.sangmo.fts.process.factoring.service;

import com.sangmo.boot.framework.common.errors.ServiceException;
import com.sangmo.boot.framework.common.errors.StandardErrors;
import com.sangmo.boot.framework.data.filter.NativeQueryBuilder;
import com.sangmo.boot.framework.data.filter.PageResult;
import com.sangmo.boot.framework.data.filter.PageSearch;
import com.sangmo.boot.framework.data.filter.ValueFilter;
import com.sangmo.boot.framework.plugin.dataview.crud.service.DelegateViewService;
import com.sangmo.boot.framework.plugin.dataview.crud.service.ViewService;
import com.sangmo.boot.framework.plugin.dataview.spi.jpa.NativeQueryBuilderFactory;
import com.sangmo.fts.basic.model.Company;
import com.sangmo.fts.process.factoring.interfaces.FfWaybillReceiveRequest;
import com.sangmo.fts.process.factoring.model.FfWaybill;
import com.sangmo.fts.process.factoring.model.FfWaybillItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;

@Service
@Transactional
public class FfWaybillService extends DelegateViewService<FfWaybill> {

    @Autowired
    private FfWaybillEntityService ffWaybillEntityService;

    @Autowired
    private FfWaybillItemEntityService ffWaybillItemEntityService;

    @Override
    protected ViewService<FfWaybill> getEntityService() {
        return ffWaybillEntityService;
    }

    public void ship(Long id) {
        FfWaybill waybill = this.get(id);
        if (!FfWaybill.States.PENDING.equals(waybill.getState())) {
            throw new ServiceException(StandardErrors.CLIENT_ERROR.getStatus(), "error.ffWaybill.has.shipped");
        }
        waybill.setState(FfWaybill.States.DISPATCHED);
        this.save(waybill);
    }

    public PageResult<FfWaybillItem> listItemsByPage(Long waybillId, PageSearch ps) {
        ps.getFilters().add(new ValueFilter("waybillId", ValueFilter.OP_EQ, waybillId));
        return ffWaybillItemEntityService.search(ps);
    }

    public void receive(Long id, FfWaybillReceiveRequest request) {
        FfWaybill waybill = this.get(id);
        if (!FfWaybill.States.DISPATCHED.equals(waybill.getState())) {
            throw new ServiceException(StandardErrors.CLIENT_ERROR.getStatus(), "error.ffWaybill.has.received");
        }
        waybill.setState(FfWaybill.States.RECEIVED);
        waybill.setReceiptTime(request.getReceiptTime());
        waybill.setReceiptPlace(request.getReceiptPlace());
        this.save(waybill);
    }

    public FfWaybill findByContractId(Long contractId) {
        return ffWaybillEntityService.findByContractId(contractId);
    }

    public PageResult<FfWaybill> selection(PageSearch ps) {
        ps.getFilters().add(new ValueFilter("state", ValueFilter.OP_EQ, FfWaybill.States.RECEIVED));
        return super.search(ps);
    }

    public PageResult<Company> sellerSelection(Long trainingId, PageSearch ps) {
        ps.setFilters(new ArrayList<>());
        NativeQueryBuilder builder = NativeQueryBuilderFactory.create()
                .putAlias("a", Company.class)
                .selectForm("SELECT a.* FROM company a ")
                .where("EXISTS (select 1 from ff_waybill fw where fw.training_id = :trainingId and fw.shipper = a.id and fw.state = 'RECEIVED' and fw.deleted = 0) ")
                .where(ps)
                .putVariable("trainingId", trainingId)
                .setAggregateWith(" group by a.id")
                .transform(Company.class);
        return builder.buildPage();
    }

}
